﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Forms;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using Resxus.Model;
using Resxus.DataAccess;
using System.ComponentModel;
using System.Windows.Data;

using System.Resources;

using Resxus.Util;

namespace Resxus.ViewModel
{
    public class MainWindowVM : WorkspaceViewModel, IEdit
    {

    #region Fields
        
        /// <summary>
        /// 리소스 파일 저장소
        /// </summary>
        public ResFilesRepository Files
        {
            get { return _files; }
        }
        readonly ResFilesRepository _files = new ResFilesRepository();

        /// <summary>
        /// 리소스 테이블 저장소
        /// </summary>
        public TableCollection Repositories
        {
            get { return this._repositories; }
        }
        readonly TableCollection _repositories = new TableCollection();

        
    #endregion //Fields

    #region Constructor

        public MainWindowVM()
        {
            this.RequestClose += new EventHandler(MainWindowVM_RequestClose);

            this.Repositories.AddRecordRepository += new Action<ResourceTable>(Repositories_AddRecordRepository);
            this.Repositories.RemoveRecordRepository += new Action<ResourceTable>(Repositories_RemoveRecordRepository);
            this.Repositories.ClearRecordRepositories += new Action(Repositories_ClearRecordRepositories);

            this.Files.RemoveFile += new Action<ResourceFile>(Files_RemoveFile);
        }        
        
    #endregion //Constructor

    #region Commands        

    #endregion //Commands

    #region Binding Properties

        /// <summary>
        /// 프로그램 타이틀
        /// </summary>
        public override string DisplayName
        {
            get
            {
                return "Resxus";
            }
        }
        
        /// <summary>
        /// 메뉴
        /// </summary>        
        public MenuBarVM MenuPanel
        {
            get
            {
                if (_MenuPanel == null)
                {
                    _MenuPanel = new MenuBarVM(this);
                }
                return _MenuPanel;
            }
        }
        private MenuBarVM _MenuPanel = null;

        /// <summary>
        /// 툴모음
        /// </summary>        
        public ToolBarVM ToolPanel
        {
            get
            {
                if (_ToolPanel == null)
                {
                    _ToolPanel = new ToolBarVM(_files);
                }
                return _ToolPanel;
            }
        }
        private ToolBarVM _ToolPanel = null;

        /// <summary>
        /// 좌측 파일리스트 패널
        /// </summary>        
        public FileListVM LeftPanel
        {
            get
            {
                if (_LeftPanel == null)
                {
                    _LeftPanel = new FileListVM(this);
                }
                return _LeftPanel;
            }
        }
        private FileListVM _LeftPanel = null;

        /// <summary>
        /// 화면에 보여지는 리소스 레코드들을 담고있는 객체
        /// </summary>
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_Workspaces == null)
                {
                    _Workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _Workspaces.CollectionChanged += new NotifyCollectionChangedEventHandler(Workspaces_CollectionChanged);
                }
                return _Workspaces;
            }
        }
        ObservableCollection<WorkspaceViewModel> _Workspaces = null;

    #endregion //Binding Properties

    #region Private Helpers

        /// <summary>
        /// 파일이 목록에서 삭제될 경우 핸들러
        /// </summary>
        /// <param name="obj">파일</param>
        void Files_RemoveFile(ResourceFile file)
        {
            var selectedTables = from table in this.Repositories
                                 where table.File.Equals(file) == true
                                 select table;            
            selectedTables.DoAll((param) => { this.Repositories.Items.Remove(param); });           
        }

        /// <summary>
        /// 현재 포커스될 탭 설정
        /// </summary>
        /// <param name="workspace">포커싱할 탭</param>
        void SetActiveWorkspace(WorkspaceViewModel workspace)
        {
            System.Diagnostics.Debug.Assert(this.Workspaces.Contains(workspace));

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);                        
        }

        /// <summary>
        /// 현재 포커스된 탭 가져오기
        /// </summary>
        /// <returns></returns>
        WorkspaceViewModel GetActiveWorkspace()
        {
            ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);            
            return collectionView.CurrentItem as WorkspaceViewModel;
        }

        /// <summary>
        /// 파일에서 레코드 로드 
        /// </summary>
        /// <param name="file">리소스 파일</param>
        /// <returns>레코드 테이블</returns>
        private ResourceTable LoadRecords(ResourceFile file)
        {
            ResourceTable repository = new ResourceTable(file);

            using (ResXResourceReader reader = new ResXResourceReader(file.FullName))
            {
                System.Collections.IDictionaryEnumerator enumerator = reader.GetEnumerator();
                while (enumerator.MoveNext() == true)
                {
                    System.Collections.DictionaryEntry entity = enumerator.Entry;
                    ResourceRecord newRecord = new ResourceRecord()
                    {
                        ID = entity.Key.ToString(),
                        Value = entity.Value.ToString()
                    };
                    repository.Items.Add(newRecord);
                }
            }

            return repository;
        }    

    #endregion //Private Helpers

    #region Public Methods

        /// <summary>
        /// 프로그램 종료시 탭 처리
        /// </summary>        
        void MainWindowVM_RequestClose(object sender, EventArgs e)
        {
            this.Workspaces.DoAll((param) => { param.CloseCommand.Execute(null); });            
        }    
        
        /// <summary>
        /// 화면에 보여지는 뷰 탭의 변화시 동작
        /// </summary>        
        void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += new EventHandler(Workspace_RequestClose);

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)                
                    workspace.RequestClose -= new EventHandler(Workspace_RequestClose);
                 
        }

        /// <summary>
        /// 탭 닫힐때 처리
        /// </summary>        
        void Workspace_RequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;
            workspace.Dispose();
            this.Workspaces.Remove(workspace);
        }
        
        void Repositories_ClearRecordRepositories()
        {

        }

        /// <summary>
        /// 레코드 테이블 제거시 처리
        /// </summary>        
        void Repositories_RemoveRecordRepository(ResourceTable obj)
        {
            var workspacesToClose = from workspace in this.Workspaces
                                    where workspace is ResourceEditVM && ((workspace as ResourceEditVM).File.Equals(obj.File) == true)
                                    select workspace as ResourceEditVM;

            workspacesToClose.DoAll((workspace) => { this.Workspaces.Remove(workspace); });
        }

        /// <summary>
        /// 레코드 테이블 추가시 처리
        /// </summary>
        /// <param name="repository">추가된 테이블</param>
        void Repositories_AddRecordRepository(ResourceTable repository)
        {
            ResourceEditVM workspace = new ResourceEditVM(this, repository);            

            this.Workspaces.Add(workspace);
            this.SetActiveWorkspace(workspace);
        }

    #endregion //Public Methods

    #region IEdit 멤버

        /// <summary>
        /// 파일 로드
        /// </summary>
        /// <param name="collection">현재 로드된 파일 목록</param>
        /// <param name="actionName">로드창 타이틀</param>
        /// <param name="action">로드시 작업</param>
        void IEdit.Load(ICollection<ResourceFile> collection, string actionName, Action<ResourceFile> action)
        {
            OpenFileDialog openDialog = new OpenFileDialog() { Title = actionName, Multiselect = true, Filter = "리소스 파일(*.resx)|*.resx|전체 파일(*.*)|*.*" };
            if (openDialog.ShowDialog() == DialogResult.OK)
            {
                //파일 목록 저장소에 파일 추가 
                string[] fileNames = openDialog.FileNames;
                foreach (var item in fileNames)
                {
                    ResourceFile file = ResourceFile.Create(item);
                    if (collection.Contains(file) == false)
                    {
                        action(file);
                    }
                }
            }            
        }

        /// <summary>
        /// 파일열기
        /// </summary>
        /// <param name="file">파일열기</param>
        void IEdit.Open(ResourceFile file)
        {
            var selectedTable = from table in this.Repositories
                                where table.File.Equals(file) == true
                                select table;
                        
            if (selectedTable.Count() == 0)
            {
                ResourceTable repository = this.LoadRecords(file);
                this.Repositories.Items.Add(repository);
            }
            else
            {
                var editWorkspaces = from workspace in this.Workspaces
                                     where workspace is ResourceEditVM && ((workspace as ResourceEditVM).File.Equals(file) == true)
                                     select workspace as ResourceEditVM;

                if (editWorkspaces.Count() > 0)
                {
                    WorkspaceViewModel workspace = editWorkspaces.First();
                    this.SetActiveWorkspace(workspace);               
                }
            }   
        }
               
        /// <summary>
        /// 저장
        /// </summary>
        /// <param name="file">저장할 파일</param>
        void IEdit.Save(ResourceFile file)
        {            
            IEdit context = this as IEdit;
            context.Save(file, file.FullName);            
        }

        /// <summary>
        /// 저장 (Save as)
        /// </summary>
        /// <param name="file">저장할 파일</param>
        /// <param name="newPath">새로운 경로</param>
        void IEdit.Save(ResourceFile file, string newPath)
        {
            IEdit edit = this as IEdit;
            var tableToSave = from table in edit.Repositories
                              where table.File.Equals(file) == true
                              select table;            

            using (ResXResourceWriter writer = new ResXResourceWriter(newPath))
            {
                ResourceTable repository = tableToSave.First();
                foreach (var item in repository)
                {
                    writer.AddResource(item.ID, item.Value);
                }

                writer.Generate();
            }
        }
   
        /// <summary>
        /// 현재 선택된 뷰
        /// </summary>
        ResourceEditVM IEdit.Current
        {
            get
            {
                return this.GetActiveWorkspace() as ResourceEditVM;
            }
        }

    #endregion

    }
}
